package cn.micai.base.concurrent;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

/**
 * @author zhaoxinguo on 2018/5/14.
 * @email sxdtzhaoxinguo@163.com
 * @qq 827358369
 * @phone 18611966723
 * @description
 */
public class BenchmarkTest {

    private Counter counter;
    private CyclicBarrier barrier;
    private int threadNum;
    private int loopNum;
    private String testName;

    public BenchmarkTest(Counter counter, int threadNum, int loopNum, String testName) {
        this.counter = counter;
        this.barrier = new CyclicBarrier(threadNum + 1); // 关卡计数 = 线程数
        this.threadNum = threadNum;
        this.loopNum = loopNum;
        this.testName = testName;
    }

    public static void main(String [] args) throws Exception {
        int threaNum = 5000;
        int loopNum = 100;
        new BenchmarkTest(new SynchronizedBenchmarkDemo(), threaNum, loopNum, "内部锁").test();
        new BenchmarkTest(new ReentrantLockUnfairBeanchmarkDemo(), threaNum, loopNum, "不公平重入锁").test();
        new BenchmarkTest(new ReentrantLockFairBeanchmarkDemo(), threaNum, loopNum, "公平重入锁").test();
    }

    public void test() throws Exception {
        for (int i=0; i < threadNum; i++) {
            new TestThread(counter, loopNum).start();
        }
        long start = System.currentTimeMillis();
        barrier.await(); // 等待所有任务线程创建，然后通过关卡，统一执行所有线程
        long end = System.currentTimeMillis();
        System.out.println(this.testName + " count value: " + counter.getValue());
        System.out.println(this.testName + " 花费时间: " + (end -start) + "毫秒");
    }

    class TestThread extends Thread {
        int loopNum = 100;
        private Counter counter;

        public TestThread(final Counter counter, int loopNum) {
            this.loopNum = loopNum;
            this.counter = counter;
        }

        @Override
        public void run() {
            try {
                barrier.await(); // 等待所有的线程开始
                for (int i=0; i < this.loopNum; i++) {
                    counter.increment();
                }
                barrier.await(); // 等待所有的线程完成
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }
}
